/**
 * @file
 * @brief rappresenta il livello LTM dell'algoritmo UCARPP
 *
 * @authors Koldar, Giskard
 * @date 6 May 2013
 */

#ifndef LTM_H_
#define LTM_H_

#include "graph.h"
#include "operations.h"
#include "solution.h"
#include "tabooState.h"
#include "LTMFrequencies.h"
#include "LTMConfiguration.h"
#include <stdbool.h>

/** Numero di iterazioni di tenure per gli archi aggiunti nella simpleConstructive. */
#define LTM_SIMPLECONSTR_ADDTENURE 0
/**sia A il numero di iterazioni da cui la soluzione STM ritornata dalla funzione executeSTM era considerata ottima dalla stessa e B
 * il numero di iterazioni LOS che l'ultima chiamata STM ha eseguito totalmente. LTM deve decidere se la soluzione riportata da STM sia gia'
 * stata anlizzata a sufficienza oppure no. Questa macro definisce la percentuale minima che A/B deve avere affinché LTM ritenga che la soluzione
 * riportata sia gia' stata intensificata. Per esempio se A=400  e B=1000 la soluzione &Sigma e' gia' stata intensificata da STM sse A>(STM_INTENSIFICATION_THRESHOLD*B)
 */
#define LTM_INTENSIFICATION_STM_THRESHOLD 0.05

//TODO documentazione
/**
 *
 * @param pgraph
 * @param configuration
 * @return
 */
Psolution executeLTM(Pgraph pgraph, PLTMConfiguration configuration);

/** costruisce una soluzione tramite un semplice algoritmo costruttivo. La soluzione ritornata ha le seguenti caratteristiche:
 * 	\li è formata da K percorsi
 * 	\li ogni camion percorre 2 volte (una in andata ed una in ritorno) uno stesso arco
 * 	\li il nodo di partenza e' il nodo deposito
 *
 *	\pre
 *		\li pg non deve essere NULL
 *		\li pg deve essere stato inizializzato con initGraph o con initCompleteGraph
 *		\li pg completo (per completarlo usare il metodo dijkstraFiller() )
 *		\li pg ha gia' inizializzato i pesi di tempo e capacita' (per inizializzarli utilizzare la funzione initSmartWeights() )
 *		\li tabooState non deve essere NULL
 *		\li sol contiene una soluzione vuota (nessun arco gia' inserito in soluzione)
 *	\post
 *		\li la memoria puntata da sol contiene una soluzione costruttiva feasible
 *
 * @param pg indica il grafo cui trovare una soluzione temporanea
 * @param sol indica la soluzione da compilare
 * @param tabooState indica una strututra in cui incamerare gli eventuali taboo inseriti nella costruttiva
 */
void buildSimpleConstructive(Pgraph pg,Psolution sol,PtabooState tabooState);

/**costruisce una soluzione tramite un semplice algoritmo costruttivo. La soluzione ritornata ha le seguenti caratteristiche:
 * \li la soluzione consta di K percorsi di camion
 * \li ogni percorso di un camion consta di un singolo arco percorso due volte (una in andata ed una in ritorno)
 * \li il nodo di partenza e' il nodo deposito
 * \li gli archi scelti sono archi totalmente a caso
 *
 * Non è necessario richiamare la funzione randomize() prima di questa funzione poiché se ne occupa la funzione stessa
 *
 * \pre
 *  \li pg non NULL
 *  \li sol non NULL
 *  \li sol contiene una soluzione vuota (nessun arco gia' inserito in soluzione)
 *  \li tabooState non NULL
 *  \li pg completato tramite dijkstraFiller()
 *  \li pg contiene pesi già inizializzati tramite la funzione initSmartWeights()
 * \post
 *  \li il puntatore sol contiene una soluzione costruttiva per l'algoritmo UCARPP
 *
 * @param pg il grafo su cui elaborare la soluzione
 * @param sol un'area di memoria contenente una soluzione perfettamente vuota
 * @param tabooState la taboostate
 */
void buildSimpleRandomConstructive(Pgraph pg,Psolution sol,PtabooState tabooState);

/**indica se il ciclo di iterazione di LTM deve finire oppure no. In pratica è la stopping rule di LTM
 *
 * @param currentIteration l'iterazione corrente di LTM
 * @param maxIterations iterazioni totali ammissibili a livello LTM
 * @return TRUE se LTM deve continuare, FALSE altrimenti
 */
bool continueLTM(int currentIteration,int maxIterations);

/**costruisce, in varie maniere, la soluzione costruttiva necessaria per lanciare STM
 *
 * \pre
 *  \li LTMiteration>0
 *  \li K non NULL
 *  \li pgraph non NULL
 *  \li ptaboostate non NULL
 *  \li fmatrices non NULL
 *  \li STMSolution non deve essere NULL se LTMiteration>2
 * \post
 *  \li in memoria viene allocata spazio contenente una nuova strututra Solution da <b>deallocare manualmente</b>
 *  \li ptabooState modificato
 *
 *
 * @param LTMiteration l'iterazione LTM attuale
 * @param K un puntatore ad una cella contenente il numero di camion utilizzabili
 * @param STMSolution indica la soluzione ricavata da una chiamata a executeSTM
 * @param pgraph il grafo su cui ricavare la soluzione
 * @param ptabooState lo stato taboo da aggiornare
 * @param fmatrices la serie di tabelle delle frequenze eventualmente da utilizzare
 * @param STMiteration il numero di iterazioni LOS eseguite da STM nell'ultima chiamata della funzione executeSTM()
 * @param STMintensification il numero di iterazioni LOS per cui la soluzione ritornata da executeSTM() era considerata ottima
 * @return una nuova istanza di Solution
 */
Psolution buildConstructiveSolution(int LTMiteration,int* K,Psolution STMSolution,Pgraph pgraph,PtabooState ptabooState,PLTMFrequencies fmatrices,int STMiteration,int STMintensification);

/**genera una soluzione costruttiva una soluzione che utilizza gli archi che sono
 * stati inseriti nelle soluzioni precedenti il minor numero di volte. La soluzione gneerata gode delle seguenti
 * proprieta':
 * \li e' formata da soli archi doppi
 * \li il percorso parte dal deposito
 * \li da ogni nodo percorso possono fuoriuscire una serie di archi doppi
 * \li il camion non percorre mai archi che sono gia' stati soddisfatti
 * \li il camion soddisfa SEMPRE gli archi da cui transita
 *
 * per esempio il disegno rappresenta una possibile soluzione. Gli archi transitati sono i meno frequenti nello storico delle soluzioni ed il percorso
 * realizzato e' TQOK.
 *
 * \dot
 * digraph dynamicConstructive{
 *	node [shape=box];
 *	edge [dir=none];
 *	A -> B A -> C A -> D
 *	B -> E B -> C
 *	C -> G
 *	G -> H G -> I
 * }
 * \enddot
 *
 * \pre
 *  \li pgraph non NULL
 *  \li matrix non NULL
 *  \li solution non NULL
 *  \li solution non contiene alcun arco (e' cioe' vuota)
 *  \li taboostate non NULL
 *  \li taboostate preferibilmente a tutti valori nulli
 *
 * \post
 *  \li in solution e' contenuta la soluzione costruttiva a bassa frequenza
 *  \li in taboostate gli archi in soluzione costruttiva hanno un TabooExpire pari a tenure
 *
 * @param pgraph il grafo su cui costreuire la soluzione
 * @param matrix una serie di matrici delle frequenze ognuna associata ad un singolo camion per cui deve essere costruita la soluzione
 * @param solution un'area di memoria dove inserire la soluzione costruttiva
 * @param taboostate indica la taboo state da aggiornare quando si inseriscono archi nella soluzione costruttiva
 * @param tenure indica per quante iterazioni gli archi che compongono la soluzione costruttiva sono in taboo
 */
void buildDynamicConstructiveWithLowFrequencyEdges(Pgraph pgraph,PLTMFrequencies matrixes,Psolution solution,PtabooState taboostate,int tenure);

//TODO documentazione
void buildDynamicConstructiveWithLowFrequencyEdgesRecursive(int node,Pgraph pgraph, PfMatrix fmatrix, PGMatrix gmatrix,int k,PvehicleState path,PtabooList taboolist,int tenure);

/**verifica se il cammino composto percorrendo 2 volte (una in andata ed una in ritorno) il particolare
 * arco soddisfa i criteri T e Q
 *
 * \pre
 *  \li edge non NULL
 *
 * @param edge l'arco da percorrere 2 volte
 * @param T la quantita' massima di tempo disponibile per un camion
 * @param Q la quantita' massima di capacita' disponibile per un camion
 * @return TRUE se i 2*edge.t<=T e edge.q<=Q; FALSE altrimenti
 */
bool simpleIsTQOK(PedgeGraph edge,int T,int Q);

#endif /* LTM_H_ */
